package com.thunbu.lib_common.utils;

import android.app.Activity;
import android.content.pm.PackageManager;
import android.content.pm.PermissionInfo;

import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;

import com.hjq.toast.ToastUtils;
import com.thunbu.lib_common.base.BaseApplication;
import com.thunbu.lib_common.function.Action;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import io.reactivex.disposables.Disposable;
import pub.devrel.easypermissions.AppSettingsDialog;
import pub.devrel.easypermissions.EasyPermissions;

import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.Manifest.permission.CAMERA;
import static android.Manifest.permission.READ_CALENDAR;
import static android.Manifest.permission.READ_CONTACTS;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.READ_PHONE_STATE;
import static android.Manifest.permission.RECORD_AUDIO;
import static android.Manifest.permission.WRITE_CALENDAR;
import static android.Manifest.permission.WRITE_CONTACTS;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;

/**
 * @author xin.zhou4
 * @since 2019/6/12
 * 动态权限封装
 */
public class DynamicPermissionHelper implements EasyPermissions.PermissionCallbacks, EasyPermissions.RationaleCallbacks {
    public static final String TAG = "DynamicPermissionHelper";

    public static final int REQUEST_CAMERA = 1;
    public static final int REQUEST_STORAGE = 2;
    public static final int REQUEST_AUDIO = 3;
    public static final int REQUEST_PHONE = 4;
    public static final int REQUEST_LOCATION = 5;
    public static final int REQUEST_CONTACTS = 6;
    public static final int REQUEST_CALENDAR = 7;
    public static final int REQUEST_CAMERA_AUDIO = 9;
    public static final Map<Integer, String[]> permsMap = new HashMap<Integer, String[]>() {{
        put(REQUEST_CAMERA, new String[]{CAMERA});
        put(REQUEST_AUDIO, new String[]{RECORD_AUDIO});
        put(REQUEST_STORAGE, new String[]{READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE});
        put(REQUEST_PHONE, new String[]{READ_PHONE_STATE});
        put(REQUEST_LOCATION, new String[]{ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION,});
        put(REQUEST_CONTACTS, new String[]{READ_CONTACTS, WRITE_CONTACTS});
        put(REQUEST_CALENDAR, new String[]{READ_CALENDAR, WRITE_CALENDAR});
        put(REQUEST_CAMERA_AUDIO, new String[]{CAMERA, RECORD_AUDIO});
    }};

    private DynamicPermission mDynamicPermission;
    private Disposable subscribe;

    private DynamicPermissionHelper() {
    }

    public static DynamicPermissionHelper getInstance() {
        return Singleton.INSTANCE.getInstance();
    }

    // 单例
    private enum Singleton {
        INSTANCE;
        private DynamicPermissionHelper helper;

        Singleton() {
            helper = new DynamicPermissionHelper();
        }

        public DynamicPermissionHelper getInstance() {
            return helper;
        }
    }

    public void requestPermissions(Activity activity, int requestCode, Action grantedAction, Action deniedAction) {
        request(activity, requestCode)
                .permissionsGranted(grantedAction)
                .permissionsDenied(deniedAction)
                .apply();
    }

    public DynamicPermission request(Activity activity, int requestCode) {
        mDynamicPermission = new DynamicPermission(activity, requestCode, () -> requestPermissions(activity));
        return mDynamicPermission;
    }

    public boolean checkPermission(String permission) {
        return ActivityCompat.checkSelfPermission(BaseApplication.myApplication, permission) == PackageManager.PERMISSION_GRANTED;
    }

    private void requestPermissions(Activity activity) {
        if (!EasyPermissions.hasPermissions(BaseApplication.myApplication, permsMap.get(mDynamicPermission.requestCode))) {
            EasyPermissions.requestPermissions(
                    activity,
                    String.format("需要%1$s权限", getLables(activity, permsMap.get(mDynamicPermission.requestCode))),
                    mDynamicPermission.requestCode,
                    permsMap.get(mDynamicPermission.requestCode)
            );
        } else {
            if (mDynamicPermission.permissionsGranted != null) {
                mDynamicPermission.permissionsGranted.run();
            }
            if (mDynamicPermission != null && mDynamicPermission.permissionDialogDismissed != null) {
                mDynamicPermission.permissionDialogDismissed.run();
            }
        }
    }

    @Override
    public void onRationaleAccepted(int requestCode) {
        if (mDynamicPermission != null && mDynamicPermission.rationaleAccepted != null) {
            mDynamicPermission.rationaleAccepted.run();
        }
        if (mDynamicPermission != null && mDynamicPermission.permissionDialogDismissed != null) {
            mDynamicPermission.permissionDialogDismissed.run();
        }
    }


    @Override
    public void onRationaleDenied(int requestCode) {
        if (mDynamicPermission != null && mDynamicPermission.rationaleDenied != null) {
            mDynamicPermission.rationaleDenied.run();
        }
        if (mDynamicPermission != null && mDynamicPermission.permissionDialogDismissed != null) {
            mDynamicPermission.permissionDialogDismissed.run();
        }
    }

    @Override
    public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
        if (permsMap.get(requestCode) != null && perms.size() == permsMap.get(requestCode).length) {
            // 全部满足
            if (mDynamicPermission != null && mDynamicPermission.permissionsGranted != null) {
                mDynamicPermission.permissionsGranted.run();
            }
            if (mDynamicPermission != null && mDynamicPermission.permissionDialogDismissed != null) {
                mDynamicPermission.permissionDialogDismissed.run();
            }
        }
    }

    @Override
    public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
        String label = getLables(ActivityManager.Companion.getInstance().getTopActivity(), perms.toArray(new String[0]));
        if (EasyPermissions.somePermissionPermanentlyDenied(ActivityManager.Companion.getInstance().getTopActivity(), perms)) {
            new AppSettingsDialog.Builder(ActivityManager.Companion.getInstance().getTopActivity())
                    .setTitle("提示")
                    .setRationale(String.format("为了您能使用%1$s功能，请开启%2$s权限！", "此", label))
                    .setPositiveButton("去设置")
                    .setNegativeButton("取消")
                    .setRequestCode(requestCode)
                    .build()
                    .show();

        } else {
            //这里之前是统一处理有toast提醒,如果不想多次打扰用户可以关闭改提醒,申请权限的时候设置
            if (mDynamicPermission != null && mDynamicPermission.mNeedToast) {
                ToastUtils.show(String.format("无法获取%1$s权限", label));
            }
            if (mDynamicPermission != null && mDynamicPermission.permissionsDenied != null) {
                mDynamicPermission.permissionsDenied.run();
            }
        }
        if (mDynamicPermission != null && mDynamicPermission.permissionDialogDismissed != null) {
            mDynamicPermission.permissionDialogDismissed.run();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
    }

    public static HashMap<String, String> cacheLables = new HashMap<>();
    public static String getLables(Activity activity, String... perms) {
        try {
            String permsKey = Arrays.toString(perms);
            if(cacheLables == null) cacheLables = new HashMap<>();
            if(!cacheLables.containsKey(permsKey)){
                PackageManager manager = activity.getPackageManager();
                StringBuilder stringBuilder = new StringBuilder();
                for (int i = 0; i < perms.length; i++) {
                    PermissionInfo permissionInfo = manager.getPermissionInfo(perms[i], 0);
                    if (permissionInfo != null && permissionInfo.labelRes > 0) {
                        stringBuilder.append(activity.getString(permissionInfo.labelRes));
                        if (i < perms.length - 1) {
                            stringBuilder.append("、");
                        }
                    }
                }
                cacheLables.put(permsKey,stringBuilder.toString());
            }
            //通过权限拿权限组拿不到
//            for (int i = 0; i < groupList.size(); i++) {
//                PermissionGroupInfo permissionGroupInfo = manager.getPermissionGroupInfo(groupList.get(i), 0);
//                if (permissionGroupInfo != null && permissionGroupInfo.labelRes > 0) {
//                    stringBuilder.append(activity.getString(permissionGroupInfo.labelRes));
//                    if (i < groupList.size() - 1) {
//                        stringBuilder.append("、");
//                    }
//                }
//            }

            return cacheLables.get(permsKey);
        } catch (Exception e) {
//            XLog.e(TAG, "getLables err:" + e.getMessage());
        }
        return "";
    }

    public class DynamicPermission {
        int requestCode;
        Action permissionsGranted, permissionsDenied, rationaleAccepted, rationaleDenied,permissionDialogDismissed;
        String labels;
        Action applyAction;
        //为了主页toast提醒少一些
        boolean mNeedToast = true;

        DynamicPermission(Activity activity, int requestCode, Action applyAction) {
            this.requestCode = requestCode;
            this.applyAction = applyAction;
            this.labels = getLables(activity, permsMap.get(requestCode));
        }

        public DynamicPermission needToast(boolean needToast) {
            mNeedToast = needToast;
            return this;
        }

        public DynamicPermission permissionsGranted(Action permissionsGranted) {
            this.permissionsGranted = permissionsGranted;
            return this;
        }

        public DynamicPermission permissionsDenied(Action permissionsDenied) {
            this.permissionsDenied = permissionsDenied;
            return this;
        }

        public DynamicPermission rationaleAccepted(Action rationaleAccepted) {
            this.rationaleAccepted = rationaleAccepted;
            return this;
        }

        public DynamicPermission rationaleDenied(Action rationaleDenied) {
            this.rationaleDenied = rationaleDenied;
            return this;
        }

        public DynamicPermission permissionDialogDismissed(Action permissionDialogDismissed) {
            this.permissionDialogDismissed = permissionDialogDismissed;
            return this;
        }

        public void apply() {
            applyAction.run();
        }
    }
}
